package com.hx.vending.service.impl;

import com.hx.vending.bean.*;
import com.hx.vending.bean.config.AlipayConfig;
import com.hx.vending.bean.config.Constants;
import com.hx.vending.bean.entity.OnlineOrderEquipment;
import com.hx.vending.bean.entity.TokenModel;
import com.hx.vending.dao.*;
import com.hx.vending.mqtt.RunnerSendMqtt;
import com.hx.vending.pay.WXPayUtil;
import com.hx.vending.service.ICustomerService;
import com.hx.vending.service.ITokenService;
import com.hx.vending.service.IWXPayService;
import com.hx.vending.util.*;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by Administrator on 2018/12/3.
 * 微信支付
 */
@Service
public class WXPayServiceImpl implements IWXPayService{


    @Autowired
    private OnlineOrderMapper onlineOrderMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private EquipmentMapper equipmentMapper;

    @Autowired
    private CustomerRechargeMapper customerRechargeMapper;

    @Autowired
    private OrderBuyMapper orderBuyMapper;

    @Autowired
    private CapitalFlowMapper capitalFlowMapper;

    @Autowired
    private RefundMapper refundMapper;

    @Autowired
    private IWXPayService iwxPayService;

    @Autowired
    private UserWithdrawMapper userWithdrawMapper;

    @Autowired
    private ICustomerService iCustomerService;

    @Autowired
    private ITokenService tokenService;

    @Resource
    private MedicineMapper medicineMapper;

    private static Logger logger = Logger.getLogger(WXPayServiceImpl.class);

    /**
     * 预支付订单返回二维码地址(扫码支付)(扫码支付未使用)
     * @param totalFee        标价金额：元
     * @param outTradeNoStr   商户订单号
     * @param onlineOrderId   线上订单id
     * @param equipmentId     设备id
     * @param goodsStr        购买的商品出货记录(货道,数量,货道,数量...)
     * @return
     * @throws Exception
     */
    public String wxNativePay(Double totalFee, String outTradeNoStr, Integer onlineOrderId, String equipmentId, String goodsStr) throws Exception {

        //32位随机字符串
        String nonceStr = WXPayUtil.generateNonceStr(32);
        //标价金额(单位：分)
        Integer fenTotalFee = (int)BigDecimalUtils.mul(totalFee, 100);
        //自定义数据（关于订单）
        String attch = onlineOrderId.toString() + "," + equipmentId + "," + goodsStr;
        //map集合放值
        SortedMap<String,String> data = new TreeMap<String,String>();

        //公众账号ID    appid
        data.put("appid", Constant.APPID);
        //商户号        mch_id
        data.put("mch_id", Constant.WX_MCH_ID);
        //设备号 	   device_info
        data.put("device_info", "WEB");
        //随机字符串 	   nonce_str
        data.put("nonce_str", nonceStr);
        //商品描述 	   body
        data.put("body", "信可网络-微信扫码支付");
        //商户订单号 	   out_trade_no
        data.put("out_trade_no", outTradeNoStr);
        //标价币种 	   fee_type
        data.put("fee_type", Constant.FEE_TYPE);
        //标价金额 	   total_fee
        data.put("total_fee", fenTotalFee.toString());
        //通知地址 	   notify_url
        data.put("notify_url", Constant.NOTIFY_URL);
        //交易类型 	   trade_type
        data.put("trade_type", Constant.TRADE_TYPE_NATIVE);
        //商品ID 	   product_id
        data.put("product_id", outTradeNoStr);
        //自定义数据  (线上订单id+设备id+出货信息)
        data.put("attach", attch);

        Map<String, String> resultMap = null;
        //生成签名
        String sign = WXPayUtil.generateSignature(data, Constant.KEY, Constants.SignType.MD5);
        System.out.println("生成签名");
        System.out.println(sign);
        //发送给微信的xml
        String outputxml = WXPayUtil.mapToXml(data,sign);
        System.out.println("生成xml");
        System.out.println(outputxml);
        //发送xml获取返回结果

        String result = WXPayUtil.requestOnce(Constant.ORDERURL, nonceStr, outputxml, 6000, 8000, false, null);

        if (ToolUtil.isNotEmpty(result)) {
            System.out.println("返回值");
            System.out.println(result);
            //将返回的xml转换为map
            resultMap = WXPayUtil.xmlToMap(result);
            System.out.println("返回的code_url:"+resultMap.get("code_url"));

            return resultMap.get("code_url");
        }else {
            return null;
        }

    }



    /**
     * 预支付订单返回预支付标识(公众号支付)
     * @return
     * @throws Exception
     */
    public Msg wxJSAPIPay(Integer customerId, Integer onlineOrderId) throws Exception {

        if (ToolUtil.isEmpty(customerId) && ToolUtil.isEmpty(onlineOrderId)) {
            return null;
        }

        //查询客户信息，即要购买商品的人的微信信息
        Customer customer = new Customer();
        customer.setCustomerId(customerId);
        Customer selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);
        if (ToolUtil.isEmpty(selectCustomer)) {
            return null;
        }
        //查询订单信息
        OnlineOrder onlineOrder = new OnlineOrder();
        onlineOrder.setOnlineOrderId(onlineOrderId);
        OnlineOrder selectOnlineOrder = this.onlineOrderMapper.selectByPrimaryKeySelective(onlineOrder);
        if (ToolUtil.isEmpty(selectOnlineOrder) || selectOnlineOrder.getOnlineOrderState() != 0) {
            return null;
        }
        //更新订单信息
        onlineOrder.setOnlineOrderOpenid(selectCustomer.getCustomerOpenId());
        onlineOrder.setOnlineOrderType("1");//微信付款
        this.onlineOrderMapper.updateByPrimaryKeySelective(onlineOrder);

        //32位随机字符串
        String nonceStr = WXPayUtil.generateNonceStr(32);
        //标价金额(单位：分)
        Integer fenTotalFee = (int)BigDecimalUtils.mul(selectOnlineOrder.getOnlineOrderMoney(), 100);
        //自定义数据(关于订单)
        String attch = onlineOrderId.toString();
        //map集合放值
        SortedMap<String,String> data=new TreeMap<String,String>();

        //公众账号ID    appid
        data.put("appid", Constant.APPID);
        //商户号        mch_id
        data.put("mch_id", Constant.WX_MCH_ID);
        //设备号 	   device_info
        data.put("device_info", "WEB");
        //随机字符串 	   nonce_str
        data.put("nonce_str", nonceStr);
        //商品描述 	   body
        data.put("body", "信可网络-微信公众号支付");
        //商户订单号 	   out_trade_no
        data.put("out_trade_no", selectOnlineOrder.getOnlineOrderMerchantNumber());
        //标价币种 	   fee_type
        data.put("fee_type", Constant.FEE_TYPE);
        //标价金额 	   total_fee
        data.put("total_fee", fenTotalFee.toString());
        //data.put("total_fee", "1");
        //通知地址 	   notify_url
        data.put("notify_url", Constant.NOTIFY_URL);
        //交易类型 	   trade_type
        data.put("trade_type", Constant.TRADE_TYPE_JSAPI);
        //自定义数据  (线上订单id)
        data.put("attach", attch);
        //用户openid
        data.put("openid", selectCustomer.getCustomerOpenId());

        Map<String, String> resultMap = null;
        //生成签名
        String sign = WXPayUtil.generateSignature(data, Constant.KEY, Constants.SignType.MD5);
        //发送给微信的xml
        String outputxml = WXPayUtil.mapToXml(data,sign);
        //发送xml获取返回结果
        String result = WXPayUtil.requestOnce(Constant.ORDERURL, nonceStr, outputxml, 6000, 8000, false, null);

        if (ToolUtil.isNotEmpty(result)) {
            //将返回的xml转换为map
            resultMap = WXPayUtil.xmlToMap(result);

            //返回的签名重新生成(微信返回的信息要重新生成签名这里要注意)
            Long time = new Date().getTime();
            SortedMap<String,String> newdata=new TreeMap<String,String>();
            newdata.put("appId", Constant.APPID);
            newdata.put("timeStamp", time.toString());
            newdata.put("nonceStr", resultMap.get("nonce_str"));
            newdata.put("package", "prepay_id="+resultMap.get("prepay_id"));
            newdata.put("signType", Constants.SignType.MD5.toString());
            String newsign = WXPayUtil.generateSignature(newdata, Constant.KEY, Constants.SignType.MD5);

            return Msg.success().add("appId", Constant.APPID).add("nonceStr", resultMap.get("nonce_str")).add("timeStamp", time.toString()).add("package", "prepay_id="+resultMap.get("prepay_id")).add("signType", Constants.SignType.MD5).add("paySign", newsign);
        }else {
            return Msg.fail();
        }

    }




    /**
     * 微信支付返回通知结果
     * @param request
     * @return
     * @throws Exception
     */
    public String WXNativeCallBack(HttpServletRequest request) throws Exception {

        System.out.println("++++++++++++++++++++支付回调++++++++++++++++++++++");

//        final AtomicInteger acquireFailCount = new AtomicInteger();
//        final AtomicInteger acquireCount = new AtomicInteger();

        //获取连接
//        final Jedis conn = new Jedis("47.105.150.35");
//        conn.select(0);
//        acquireCount.incrementAndGet();
        //加锁
//        String WXPayLock = RedisUtil.acquireLockWithTimeOut(conn, "WXPayCallBack", 100, 1);
//        if (WXPayLock != null) {System.out.println(WXPayLock+"加锁++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
            //加锁成功后，执行

//        new Thread() {
//
//        }.start();


            //接收解析返回的数据
                InputStream inStream = request.getInputStream();
                int _buffer_size = 1024;
                if (inStream != null) {
                    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                    byte[] tempBytes = new byte[_buffer_size];
                    int count = -1;
                while ((count = inStream.read(tempBytes, 0, _buffer_size)) != -1) {
                    outStream.write(tempBytes, 0, count);
                }
                tempBytes = null;
                outStream.flush();
                //将流转换成字符串
                String result = new String(outStream.toByteArray(), "UTF-8");
                //将XML格式转化成MAP格式数据
                Map<String, String> resultMap=WXPayUtil.xmlToMap(result);

                //验证签名是否正确，签名不正确返回失败的结果
                if (!WXPayUtil.isSignatureValid(resultMap, Constant.KEY, Constants.SignType.MD5)) {
                    logger.error("签名错误");
                    return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[NO]]></return_msg></xml>";
                }

                //获取自定义数据
                String attachStr =  resultMap.get("attach");
                //线上订单id
                Integer onlineOrderId = Integer.parseInt(attachStr);

                //判断订单
                OnlineOrder onlineOrder = new OnlineOrder();
                onlineOrder.setOnlineOrderId(onlineOrderId);
                OnlineOrder selectOnlineOrder = this.onlineOrderMapper.selectByPrimaryKeySelective(onlineOrder);
                if (ToolUtil.isNotEmpty(selectOnlineOrder)) {
                    if (selectOnlineOrder.getOnlineOrderState() == 1 || selectOnlineOrder.getOnlineOrderState() == 2) {
                        //已经支付过的订单
                        return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[NO]]></return_msg></xml>";
                    }else {
                        //已支付状态
                        onlineOrder.setOnlineOrderState(1);
                        //微信订单号
                        onlineOrder.setOnlineOrderDealNumber(resultMap.get("transaction_id"));
                        this.onlineOrderMapper.updateByPrimaryKeySelective(onlineOrder);

                        //如果在特殊需求的中药表里有该订单的信息，还要修改中药订单的状态
                        Medicine medicine = new Medicine();
                        medicine.setMedicineOrderId(onlineOrderId);
                        Medicine selectMedicine = this.medicineMapper.selectByPrimaryKeySelective(medicine);
                        if (ToolUtil.isNotEmpty(selectMedicine)) {
                            medicine.setMedicineStatus(1);
                            this.medicineMapper.updateStatusByOrderId(medicine);
                        }

                        //给商户添加余额并添加余额明细
                        if (ToolUtil.isNotEmpty(selectOnlineOrder.getOnlineOrderUserId())) {
                            User user = new User();
                            user.setUserId(selectOnlineOrder.getOnlineOrderUserId());
                            User selectUser = this.userMapper.selectByPrimaryKey(user);
                            user.setUserMoney(BigDecimalUtils.add(selectUser.getUserMoney(), selectOnlineOrder.getOnlineOrderMoney()));
                            user.setUserWechatBalance(BigDecimalUtils.add(selectUser.getUserWechatBalance(), selectOnlineOrder.getOnlineOrderMoney()));
                            this.userMapper.updateByPrimaryKeySelective(user);

                            CapitalFlow capitalFlow = new CapitalFlow();
                            capitalFlow.setCapitalFlowUserId(selectOnlineOrder.getOnlineOrderUserId());
                            capitalFlow.setCapitalFlowTransactionNumber(onlineOrder.getOnlineOrderDealNumber());
                            capitalFlow.setCapitalFlowTransactionAmount(selectOnlineOrder.getOnlineOrderMoney());
                            capitalFlow.setCapitalFlowPaymentType(1);
                            capitalFlow.setCapitalFlowTransactionType(4);
                            capitalFlow.setCapitalFlowTime(DateUtil.getTime());
                            capitalFlow.setCapitalFlowUserMoney(user.getUserMoney());
                            capitalFlow.setCapitalFlowState(2);
                            capitalFlow.setCapitalFlowRemarks("商户收益");
                            this.capitalFlowMapper.insertSelective(capitalFlow);
                        }
                    }
                }

                //发送出货的MQTT消息
                RunnerSendMqtt runnerSendMqtt = new RunnerSendMqtt();
                runnerSendMqtt.setMessage(selectOnlineOrder.getOnlineOrderEquipmentId());
                runnerSendMqtt.setRedisTemplate(redisTemplate);
                runnerSendMqtt.setTheme("Delivery");
                runnerSendMqtt.setThreadName("出货指令");
                runnerSendMqtt.setRedisKey("DeliveryReceive-" + selectOnlineOrder.getOnlineOrderEquipmentId());
                runnerSendMqtt.setOnlineOrderId(onlineOrderId);
                runnerSendMqtt.start();


                //开启了订单推送
                Equipment equipment = new Equipment();
                equipment.setEquipmentId(selectOnlineOrder.getOnlineOrderEquipmentId());
                Equipment selectEquipment = this.equipmentMapper.selectByPrimary(equipment);
                User user = new User();
                user.setUserId(selectEquipment.getEquipmentUserId());
                User selectUser = this.userMapper.selectByPrimaryKey(user);
                if (selectUser != null && selectUser.getUserOrderPush().equals("1")){
                    String pushMessage = "订单推送详情:\n设备ID:%s\n商家订单号:%s\n微信订单号:%s\n订单金额:%s\n支付方式:%s";
                    String orderType = null;
                    if (selectOnlineOrder.getOnlineOrderType().equals("1")) {
                        orderType = "微信";
                    }else if (selectOnlineOrder.getOnlineOrderType().equals("2")) {
                        orderType = "支付宝";
                    }
                    PushUtils.getInstance().pushMessage(selectUser.getUserAccount(),String.format(pushMessage, selectEquipment.getEquipmentId(), selectOnlineOrder.getOnlineOrderMerchantNumber(),
                            resultMap.get("transaction_id"), selectOnlineOrder.getOnlineOrderMoney(), orderType));
                }

            }


            //解锁
//            RedisUtil.releaseLock(conn, "WXPayCallBack", WXPayLock, 100);System.out.println("解锁+++++++++++++++++++++++++++++++++++++++++++++");
//            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            return "SUCCESS";
//        } else {
//            acquireFailCount.incrementAndGet();
//        }

//        return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[NO]]></return_msg></xml>";
    }


    /**
     * 授权登陆重定向(客户购买商品Android)
     * @param code
     * @param state   订单id
     * @return
     */
    public String wxChatRedirect(String code, String state){

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

        //定义地址
        String requestURL = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", Constant.APPID, Constant.AppSecret,code);
        //请求地址，获取返回信息
        Map<String, Object> resultMap = WXPayUtil.SendRequest(requestURL, null, "GET");
        String id = "";
        if(null != resultMap){
            String openid=(String)resultMap.get("openid");System.out.println("openid:"+openid);
            String token=(String)resultMap.get("access_token");System.out.println("token:"+token);

            //获取用户信息请求url
            String userInfoURL = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s", token, openid, Constant.LANG);
            //获取返回信息
            Map<String, Object> userInfoMap = WXPayUtil.SendRequest(userInfoURL, null, "GET");

            if (null != userInfoMap) {

                //将信息保存到客户表
                Customer customer = new Customer();
                customer.setCustomerOpenId(openid);

                //根据openid查询,判断用户是否存在
                Customer selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);

                customer.setCustomerName(userInfoMap.get("nickname").toString());
                customer.setCustomerPhoto(userInfoMap.get("headimgurl").toString());
                customer.setCustomerSex(userInfoMap.get("sex").toString());
                customer.setCustomerType(1);//微信用户
                customer.setCustomerCountry(userInfoMap.get("city").toString());
                customer.setCustomerCity(userInfoMap.get("city").toString());
                customer.setCustomerProvince(userInfoMap.get("province").toString());

                //查询订单设备信息
                OnlineOrderEquipment onlineOrderEquipment = this.onlineOrderMapper.selectOnlineOrderEquipment(Integer.parseInt(state));
                if (ToolUtil.isEmpty(onlineOrderEquipment) && ToolUtil.isEmpty(onlineOrderEquipment.getEquipmentUserId())) {
                    return "该设备下无商户注册！";
                }
                //添加用户关联信息
                CustomerRecharge customerRecharge = new CustomerRecharge();
                customerRecharge.setCustomerRechargeUserId(onlineOrderEquipment.getEquipmentUserId());

                if (ToolUtil.isNotEmpty(selectCustomer)) {
                    //更新客户信息
                    customer.setCustomerId(selectCustomer.getCustomerId());
                    this.customerMapper.updateByPrimaryKeySelective(customer);
                    customerRecharge.setCustomerRechargeCustomerId(selectCustomer.getCustomerId());
                }else{
                    //添加新的客户信息
                    this.customerMapper.insertSelective(customer);
                    Customer getIdCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);
                    customerRecharge.setCustomerRechargeCustomerId(getIdCustomer.getCustomerId());
                }

                //保存商户客户关联信息(查询如果存在了就不插入了)
                List<CustomerRecharge> customerRechargeList = this.customerRechargeMapper.selectByExampleSelective(customerRecharge);
                if (customerRechargeList.size() <= 0) {
                    this.customerRechargeMapper.insertSelective(customerRecharge);
                }

                //更新订单信息
                OnlineOrder onlineOrder = new OnlineOrder();
                onlineOrder.setOnlineOrderId(Integer.parseInt(state));
                onlineOrder.setOnlineOrderOpenid(openid);
                onlineOrder.setOnlineOrderType("1");
                this.onlineOrderMapper.updateByPrimaryKeySelective(onlineOrder);

                id=customerRecharge.getCustomerRechargeCustomerId().toString();
                //Cookie暂时未使用
//                //实例化一个Cookie
//                Cookie cookie = new Cookie("customerId", customerRecharge.getCustomerRechargeCustomerId().toString());
//                //生存时间
//                cookie.setMaxAge(3600 * 24);
//                //设置cookie路径
//                cookie.setPath("/");
//                cookie.setHttpOnly(false);
//                //写入肯定是要用response
//                response.addCookie(cookie);
            }
        }

        //扫描二维码成功,关闭二维码显示
        try {
            OnlineOrder onlineOrder = new OnlineOrder();
            onlineOrder.setOnlineOrderId(Integer.parseInt(state));
            OnlineOrder selectOnlineOrder = this.onlineOrderMapper.selectByPrimaryKeySelective(onlineOrder);
            PubMsg.publish(selectOnlineOrder.getOnlineOrderEquipmentId() + "," + ToolUtil.generateNonceStr(4), "ScanResponse/" + selectOnlineOrder.getOnlineOrderEquipmentId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "redirect:"+Constant.REDIRECTURL+"/"+state+"/"+id;
    }


    /**
     * 授权登陆重定向(客户购买商品web)
     * @param code
     * @param state  设备id
     * @return
     */
    public String wxChatRedirectWeb(String code, String state){

        Integer id = null;

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();


        //先从缓存里获取code，然后如果有的话，就不进行操作
        String redisMessage = redisTemplate.boundValueOps("wxcode:" + code).get();
        if (ToolUtil.isNotEmpty(redisMessage)) {
            logger.error("缓存里的openid"+redisMessage);
            //保存微信授权的信息
            Customer customer = new Customer();
            customer.setCustomerOpenId(redisMessage);
            //根据openid查询,判断用户是否存在
            Customer selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);
            if (ToolUtil.isNotEmpty(selectCustomer)) {

                //查询设备信息
                Equipment equipment = new Equipment();
                equipment.setEquipmentId(state);
                Equipment selectEquipment = this.equipmentMapper.selectByPrimary(equipment);
                if (ToolUtil.isEmpty(selectEquipment) || ToolUtil.isEmpty(selectEquipment.getEquipmentUserId())) {
                    return "该设备下无商户注册！";
                }
                //添加用户关联信息
                CustomerRecharge customerRecharge = new CustomerRecharge();
                customerRecharge.setCustomerRechargeUserId(selectEquipment.getEquipmentUserId());

                customerRecharge.setCustomerRechargeCustomerId(selectCustomer.getCustomerId());

                id= customerRecharge.getCustomerRechargeCustomerId();

                //保存商户客户关联信息(查询如果存在了就不插入了)
                List<CustomerRecharge> customerRechargeList = this.customerRechargeMapper.selectByExampleSelective(customerRecharge);
                if (customerRechargeList.size() <= 0) {
                    this.customerRechargeMapper.insertSelective(customerRecharge);
                }
            }
        }else {

            //定义地址
            String requestURL = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", Constant.APPID, Constant.AppSecret,code);
            //请求地址,获取返回信息
            Map<String, Object> resultMap = WXPayUtil.SendRequest(requestURL, null, "GET");

            if(null != resultMap){

                if (ToolUtil.isEmpty(resultMap.get("openid")) || ToolUtil.isEmpty(resultMap.get("access_token"))) {
                    logger.error("购买微信授权登陆错误：错误码（"+resultMap.get("errcode")+")");
                    return "redirect:" + Constant.REDIRECTWEBURL + "/" + state + "/" + id;
                }

                String openid=(String)resultMap.get("openid");logger.error("openid:"+openid);
                String token=(String)resultMap.get("access_token");logger.error("token:"+token);

                //code只能使用一次，未使用五分钟后过期，所以注意不能使用相同的code获取两次openid
                //保存数据
                //如果检测到使用了相同的code那么就不进行操作了.
                redisTemplate.boundValueOps("wxcode:" + code).set((String)resultMap.get("openid"), Constants.MQTT_EXPIRES_HOUR, TimeUnit.SECONDS);

                //获取用户信息请求url
                String userInfoURL = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s", token, openid, Constant.LANG);
                //获取返回信息
                Map<String, Object> userInfoMap = WXPayUtil.SendRequest(userInfoURL, null, "GET");

                if (null != userInfoMap) {

                    //将信息保存到客户表
                    Customer customer = new Customer();
                    customer.setCustomerOpenId(openid);

                    //根据openid查询,判断用户是否存在
                    Customer selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);

                    customer.setCustomerName(userInfoMap.get("nickname").toString());
                    customer.setCustomerPhoto(userInfoMap.get("headimgurl").toString());
                    customer.setCustomerSex(userInfoMap.get("sex").toString());
                    customer.setCustomerType(1);//微信用户
                    customer.setCustomerCountry(userInfoMap.get("city").toString());
                    customer.setCustomerCity(userInfoMap.get("city").toString());
                    customer.setCustomerProvince(userInfoMap.get("province").toString());

                    //查询设备信息
                    Equipment equipment = new Equipment();
                    equipment.setEquipmentId(state);
                    Equipment selectEquipment = this.equipmentMapper.selectByPrimary(equipment);
                    if (ToolUtil.isEmpty(selectEquipment) || ToolUtil.isEmpty(selectEquipment.getEquipmentUserId())) {
                        return "该设备下无商户注册！";
                    }

                    //添加用户关联信息
                    CustomerRecharge customerRecharge = new CustomerRecharge();
                    customerRecharge.setCustomerRechargeUserId(selectEquipment.getEquipmentUserId());

                    if (ToolUtil.isNotEmpty(selectCustomer)) {
                        //更新客户信息
                        customer.setCustomerId(selectCustomer.getCustomerId());
                        this.customerMapper.updateByPrimaryKeySelective(customer);
                        customerRecharge.setCustomerRechargeCustomerId(selectCustomer.getCustomerId());
                    }else{
                        //添加新的客户信息
                        this.customerMapper.insertSelective(customer);
                        Customer getIdCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);
                        customerRecharge.setCustomerRechargeCustomerId(getIdCustomer.getCustomerId());
                    }

                    id= customerRecharge.getCustomerRechargeCustomerId();

                    //保存商户客户关联信息(查询如果存在了就不插入了)
                    List<CustomerRecharge> customerRechargeList = this.customerRechargeMapper.selectByExampleSelective(customerRecharge);
                    if (customerRechargeList.size() <= 0) {
                        this.customerRechargeMapper.insertSelective(customerRecharge);
                    }

                    //Cookie暂时无用
//                //实例化一个Cookie
//                Cookie cookie = new Cookie("customerId", customerRecharge.getCustomerRechargeCustomerId().toString());
//                //生存时间
//                cookie.setMaxAge(3600 * 24);
//                //设置cookie路径
//                cookie.setPath("http://star-hi.cn/");
//                //写入肯定是要用response
//                response.addCookie(cookie);
                }
            }
        }

        //重定向state：设备id   id：客户信息id
        return "redirect:" + Constant.REDIRECTWEBURL + "/" + state + "/" + id;
    }

    /**
     * 微信提现到微信零钱
     * @return
     */
    public Msg wxCashWithdrawal(Integer userId, Double money, Integer withDrawalId){

        if (ToolUtil.isEmpty(userId) || ToolUtil.isEmpty(money)) {
            return Msg.fail().add("msg", "用户信息或提现金额为空");
        }

        //用户信息
        User user = new User();
        user.setUserId(userId);
        User selectUser = this.userMapper.selectByPrimaryKey(user);
        if (ToolUtil.isEmpty(selectUser)) {
            return Msg.fail().addCode(101).add("msg", "该用户不存在");
        }
        if (selectUser.getUserWechatBalance() < money) {
            return Msg.fail().addCode(102).add("msg", "商户微信可提现余额不足");
        }
        if (ToolUtil.isEmpty(selectUser.getUserCustomerId())) {
            return Msg.fail().addCode(103).add("msg", "微信唯一标识未获取");
        }
        if (ToolUtil.isEmpty(selectUser.getUserWechatRealName())) {
            return Msg.setAllMsg(100, "未填写微信真实姓名");
        }

        //查询提现微信的信息
        Customer customer = new Customer();
        customer.setCustomerId(selectUser.getUserCustomerId());
        Customer selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);
        if (ToolUtil.isEmpty(selectCustomer)) {
            return Msg.fail();
        }
        //计算手续费
        Float proportion = selectUser.getUserWithdrawproportion();// 商户提现比例
        double drawMoney = Double.parseDouble(proportion.toString());
        double pool = BigDecimalUtils.mul(money, drawMoney / 100);// 手续费
        pool = BigDecimalUtils.round(Math.ceil(pool*100), 100, 2);//将手续费换算为分，向上取整（计算手续费的时候，不足一分的算作一分）
        //32位随机字符串
        String nonceStr = WXPayUtil.generateNonceStr(32);
        //提现金额
        double drawmoney = BigDecimalUtils.mul(BigDecimalUtils.sub(money, pool), 100);
        Integer drawFee = (int)drawmoney;
        if (drawFee < 30) {
            //微信体现到零钱最少0.3元
            return Msg.fail().addCode(104).add("msg", "微信提现最低金额为" + BigDecimalUtils.add(pool, 0.3) + "元");
        }
        //商户订单号
        String outTradeNoStr = DateUtil.getAllTime()+ToolUtil.generateNonceStr(4);
        //map集合放值
        SortedMap<String,String> data=new TreeMap<String,String>();

        //公众账号ID    appid
        data.put("mch_appid", Constant.APPID);
        //商户号        mch_id
        data.put("mchid", Constant.WX_MCH_ID);
        //随机字符串 	   nonce_str
        data.put("nonce_str", nonceStr);
        //商户订单号 	   out_trade_no
        data.put("partner_trade_no", outTradeNoStr);
        //金额 	   total_fee
        data.put("amount", drawFee.toString());
        //用户openid
        data.put("openid", selectCustomer.getCustomerOpenId());
        //校检用户姓名
        data.put("check_name", Constant.TRANSFERSCHECK);
        //真实姓名
        data.put("re_user_name", selectUser.getUserWechatRealName());
        //备注
        data.put("desc", "信可网络微信提现");
        //微信设置的可提现的ip
        data.put("spbill_create_ip", Constant.TRANSFERSIP);

        Map<String, String> resultMap = null;

        try {
            //生成签名
            String sign = WXPayUtil.generateSignature(data, Constant.KEY, Constants.SignType.MD5);
            //发送给微信的xml
            String outputxml = WXPayUtil.mapToXml(data,sign);
            //发送xml获取返回结果
            String resource =this.getClass().getClassLoader().getResource("/").getPath();

            String result = WXPayUtil.requestOnce(Constant.TRANSFERSURL, nonceStr, outputxml, 6000, 8000, true, resource);

            if (ToolUtil.isNotEmpty(result)) {
                System.out.println(result);
                //将返回的xml转换为map
                resultMap = WXPayUtil.xmlToMap(result);

                //修改余额(先将余额扣除，防止失败后多次提现)
                user.setUserMoney(BigDecimalUtils.sub(selectUser.getUserMoney(),money));
                user.setUserWechatBalance(BigDecimalUtils.sub(selectUser.getUserWechatBalance(),money));
                this.userMapper.updateByPrimaryKeySelective(user);
                //提现记录
                UserWithdraw userWithdraw = new UserWithdraw();
                userWithdraw.setUserWithdrawUserid(userId);
                userWithdraw.setUserWithdrawMoney(money);
                userWithdraw.setUserWithdrawTime(DateUtil.getTime());
                userWithdraw.setUserWithdrawOutBizNo(outTradeNoStr);
                userWithdraw.setUserWithdrawOrderNo(resultMap.get("payment_no"));
                userWithdraw.setUserWithdrawAccount(resultMap.get("payment_time"));
                userWithdraw.setUserWithdrawType(0);
                userWithdraw.setUserWithdrawPractical(BigDecimalUtils.round(drawmoney, 100, 2));

                if (resultMap.get("return_code").equals("SUCCESS") && resultMap.get("result_code").equals("SUCCESS")) {
                    //提现成功

                    //流水记录
                    CapitalFlow capitalFlow = new CapitalFlow();
                    capitalFlow.setCapitalFlowUserId(userId);
                    capitalFlow.setCapitalFlowTransactionNumber(resultMap.get("payment_no"));
                    capitalFlow.setCapitalFlowTransactionAmount(money);
                    capitalFlow.setCapitalFlowPaymentType(1);
                    capitalFlow.setCapitalFlowTransactionType(2);
                    capitalFlow.setCapitalFlowTime(resultMap.get("payment_time"));
                    capitalFlow.setCapitalFlowUserMoney(BigDecimalUtils.sub(selectUser.getUserMoney(),money));
                    capitalFlow.setCapitalFlowState(2);
                    capitalFlow.setCapitalFlowRemarks("微信提现到零钱");
                    this.capitalFlowMapper.insertSelective(capitalFlow);
                    CapitalFlow selectCapitalFlow = this.capitalFlowMapper.selectByPrimaryKeySelective(capitalFlow);

                    if (ToolUtil.isNotEmpty(selectCapitalFlow)) {
                        userWithdraw.setUserWithdrawFlowId(selectCapitalFlow.getCapitalFlowId());
                    }
                    userWithdraw.setUserWithdrawState(2);
                    userWithdraw.setUserWithdrawRemark("提现成功");
                    if (ToolUtil.isNotEmpty(withDrawalId)) {
                        //如果传入了提现记录id，就在原记录的基础上修改状态
                        userWithdraw.setUserWithdrawId(withDrawalId);
                        userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw);
                    }else {
                        //如果没有传入体现记录id，就添加一条新的记录
                        userWithdrawMapper.insertSelective(userWithdraw);
                    }

                    return Msg.success();
                }else if (resultMap.get("result_code").equals("FAIL") && !resultMap.get("err_code").equals("SYSTEMERROR")) {
                    //提现失败
                    userWithdraw.setUserWithdrawState(0);
                    userWithdraw.setUserWithdrawRemark("提现失败");
                    if (ToolUtil.isNotEmpty(withDrawalId)) {
                        //如果传入了提现记录id，就在原记录的基础上修改状态
                        userWithdraw.setUserWithdrawId(withDrawalId);
                        userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw);
                    }else {
                        userWithdrawMapper.insertSelective(userWithdraw);
                    }
                    //将钱返还到账户
                    user.setUserMoney(selectUser.getUserMoney());
                    user.setUserWechatBalance(selectUser.getUserWechatBalance());
                    this.userMapper.updateByPrimaryKeySelective(user);

                    if (resultMap.get("err_code").equals("NO_AUTH")) {
                        return Msg.fail().addCode(105).add("msg", "商户平台异常，请稍后重试");
                    }else if (resultMap.get("err_code").equals("AMOUNT_LIMIT")) {
                        return Msg.fail().addCode(106).add("msg", "金额超限");
                    }else if (resultMap.get("err_code").equals("OPENID_ERROR")) {
                        return Msg.fail().addCode(107).add("msg", "Openid错误");
                    }else if (resultMap.get("err_code").equals("MONEY_LIMIT")) {
                        return Msg.fail().addCode(108).add("msg", "今日提现超额");
                    }else if (resultMap.get("err_code").equals("V2_ACCOUNT_SIMPLE_BAN")) {
                        return Msg.fail().addCode(109).add("msg", "微信用户未实名，无法提现");
                    }else if (resultMap.get("err_code").equals("SENDNUM_LIMIT")) {
                        return Msg.fail().addCode(110).add("msg", "提现请求次数受限");
                    }else if (resultMap.get("err_code").equals("NOTENOUGH")) {
                        String pushMessage = "微信提现余额不足";
                        PushUtils.getInstance().pushMessage("18654568090", pushMessage);
                        PushUtils.getInstance().pushMessage("15562649697", pushMessage);

                        return Msg.fail().addCode(111).add("msg", "服务器正在忙于结算，请5-10分钟后再试");
                    }else if (resultMap.get("err_code").equals("NAME_MISMATCH")) {
                        return Msg.setAllMsg(112, "真实姓名与微信真实姓名不一致");
                    }else {
                        return Msg.fail().add("msg", "提现失败");
                    }
                }else if (resultMap.get("result_code").equals("FAIL") && resultMap.get("err_code").equals("SYSTEMERROR")) {
                    //发生这种情况要使用原订单号重试，查询改订单的状态是完成还是失败

                    //32位随机字符串
                    String TransferNonceStr = WXPayUtil.generateNonceStr(32);

                    SortedMap<String,String> transferData=new TreeMap<String,String>();

                    //随机字符串
                    transferData.put("nonce_str", TransferNonceStr);
                    //商户订单号要使用原商户订单号
                    transferData.put("partner_trade_no", outTradeNoStr);
                    //商户号
                    transferData.put("mch_id", Constant.WX_MCH_ID);
                    //appid
                    transferData.put("appid", Constant.APPID);

                    //生成签名
                    String transferSign = WXPayUtil.generateSignature(transferData, Constant.KEY, Constants.SignType.MD5);
                    //发送给微信的xml
                    String transferOutputxml = WXPayUtil.mapToXml(transferData,transferSign);
                    //发送xml获取返回结果
                    String transferResource =this.getClass().getClassLoader().getResource("/").getPath();
                    String selectTransferInfo = WXPayUtil.requestOnce(Constant.GETTRANSFERINFO, TransferNonceStr, transferOutputxml, 6000, 8000, true, transferResource);
                    //将返回的xml转换为map
                    Map<String, String> transferResultMap = WXPayUtil.xmlToMap(selectTransferInfo);
                    if (ToolUtil.isNotEmpty(transferResultMap) && ToolUtil.isNotEmpty(transferResultMap.get("status"))) {
                        if (transferResultMap.get("status").equals("SUCCESS")) {//转账成功
                            userWithdraw.setUserWithdrawState(2);
                            userWithdraw.setUserWithdrawRemark("提现成功");
                        }else if (transferResultMap.get("status").equals("FAILED")) {//转账失败
                            userWithdraw.setUserWithdrawState(0);//失败
                            userWithdraw.setUserWithdrawRemark("提现失败");
                            //将钱返还到账户
                            user.setUserMoney(BigDecimalUtils.add(selectUser.getUserMoney(),money));
                            user.setUserWechatBalance(BigDecimalUtils.add(selectUser.getUserWechatBalance(),money));
                            this.userMapper.updateByPrimaryKeySelective(user);
                        }else if (transferResultMap.get("status").equals("PROCESSING")) {//正在处理
                            userWithdraw.setUserWithdrawState(1);//处理中
                            userWithdraw.setUserWithdrawRemark("处理中");
                        }
                        if (ToolUtil.isNotEmpty(withDrawalId)) {
                            //如果传入了提现记录id，就在原记录的基础上修改状态
                            userWithdraw.setUserWithdrawId(withDrawalId);
                            userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw);
                        }else {
                            userWithdrawMapper.insertSelective(userWithdraw);
                        }
                    }else {
                        userWithdraw.setUserWithdrawState(1);
                        userWithdraw.setUserWithdrawRemark("处理中");
                        if (ToolUtil.isNotEmpty(withDrawalId)) {
                            //如果传入了提现记录id，就在原记录的基础上修改状态
                            userWithdraw.setUserWithdrawId(withDrawalId);
                            userWithdrawMapper.updateByPrimaryKeySelective(userWithdraw);
                        }else {
                            userWithdrawMapper.insertSelective(userWithdraw);
                        }
                    }
                }
            }else {
                return Msg.fail().add("msg", "返回结果为空");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Msg.fail().add("msg", "提现失败");
    }


    /**
     * 关闭订单
     * @param outTradeNo 商户订单号
     * @return
     */
    public String closeOrder(String outTradeNo) {

        if (ToolUtil.isNotEmpty(outTradeNo)) {
            //map集合放值
            SortedMap<String,String> data=new TreeMap<String,String>();

            //公众账号ID    appid
            data.put("mch_appid", Constant.APPID);
            //商户号        mch_id
            data.put("mchid", Constant.WX_MCH_ID);
            //商户订单号
            data.put("out_trade_no", outTradeNo);
            //32位随机字符串
            String nonceStr = WXPayUtil.generateNonceStr(32);
            data.put("nonce_str", nonceStr);

            Map<String, String> resultMap = null;
            //生成签名
            String sign = null;
            try {
                sign = WXPayUtil.generateSignature(data, Constant.KEY, Constants.SignType.MD5);
                System.out.println("生成签名");
                System.out.println(sign);
                //发送给微信的xml
                String outputxml = WXPayUtil.mapToXml(data,sign);
                System.out.println("生成xml");
                System.out.println(outputxml);
                //发送xml获取返回结果
                String result = WXPayUtil.requestOnce(Constant.ORDERURL, nonceStr, outputxml, 6000, 8000, false, null);

                if (ToolUtil.isNotEmpty(result)) {
                    //将返回的xml转换为map
                    resultMap = WXPayUtil.xmlToMap(result);

                    if (resultMap.get("return_code").equals("SUCCESS") && resultMap.get("return_msg").equals("OK")) {
                        return "OK";
                    }else {
                        return null;
                    }
                }else {
                    return null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }else {
            return null;
        }
        return null;
    }


    /**
     * 判断跳转微信支付还是支付宝支付
     * @param request
     * @return
     */
    public String paymentJump(HttpServletRequest request, String onlineOrderId) {

        String userAgent = request.getHeader("user-agent");

        if (ToolUtil.isNotEmpty(userAgent)) {

            if (userAgent.contains("AlipayClient")) {
                //扫描二维码成功,关闭二维码显示
                try {
                    OnlineOrder onlineOrder = new OnlineOrder();
                    onlineOrder.setOnlineOrderId(Integer.parseInt(onlineOrderId));
                    OnlineOrder selectOnlineOrder = this.onlineOrderMapper.selectByPrimaryKeySelective(onlineOrder);
                    PubMsg.publish(selectOnlineOrder.getOnlineOrderEquipmentId() + "," + ToolUtil.generateNonceStr(4), "ScanResponse/" + selectOnlineOrder.getOnlineOrderEquipmentId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //支付宝
                String redirect_uri = "http://star-hi.cn/vending/alipay/aliPayRedirect";
                String url = String.format("https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=%s&scope=%s&redirect_uri=%s&state=%s",
                        AlipayConfig.APPID, "auth_user",redirect_uri,onlineOrderId);
                //2.发送请求
                return "redirect:" + url;
            } else if (userAgent.contains("MicroMessenger")) {
                //微信授权登陆
                String requestURL=String.format("https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect", Constant.APPID, Constant.REDIRECT_URL, Constant.SCOPE_SNSAPI_USERINFO, onlineOrderId);
                return "redirect:"+requestURL;
            }
            return "";
        }else {
            return "";
        }
    }


    /**
     * 订单退款
     * @param onlineOrderId      订单id
     * @param refundMoney        退款金额
     * @return
     */
    public Msg wxRefund(Integer onlineOrderId, Double refundMoney, Integer orderBuyId) {

        //查询订单信息
        OnlineOrder onlineOrder = new OnlineOrder();
        onlineOrder.setOnlineOrderId(onlineOrderId);
        OnlineOrder selectOnlineOrder = this.onlineOrderMapper.selectByPrimaryKeySelective(onlineOrder);
        //查询商户信息
        User user = new User();
        user.setUserId(selectOnlineOrder.getOnlineOrderUserId());
        User selectUser = this.userMapper.selectByPrimaryKey(user);

        if (ToolUtil.isNotEmpty(selectOnlineOrder) && ToolUtil.isNotEmpty(selectUser)) {

            if (selectUser.getUserWechatBalance() < refundMoney) {
                return Msg.setAllMsg(100, "商户余额不足");
            }

            //32位随机字符串
            String nonceStr = WXPayUtil.generateNonceStr(32);
            SortedMap<String,String> data=new TreeMap<String,String>();

            //公众账号ID    appid
            data.put("appid", Constant.APPID);
            //商户号        mch_id
            data.put("mch_id", Constant.WX_MCH_ID);
            //随机字符串 	   nonce_str
            data.put("nonce_str", nonceStr);
            //订单号
            data.put("transaction_id", selectOnlineOrder.getOnlineOrderDealNumber());
            //订单金额
            double money = selectOnlineOrder.getOnlineOrderMoney()*100;
            Integer totalFee = (int)money;
            data.put("total_fee", totalFee.toString());
            //退款金额
            double refundmoney = refundMoney*100;
            Integer refundFee = (int)refundmoney;
            data.put("refund_fee", refundFee.toString());
            //标价币种 	   fee_type
            data.put("refund_fee_type", Constant.FEE_TYPE);
            //退款原因
            data.put("refund_desc", "出货失败!!!!");
            //退款单号
            data.put("out_refund_no", WXPayUtil.onlineOrderMerchantNumber());
            try {
                //生成签名
                String sign = WXPayUtil.generateSignature(data, Constant.KEY, Constants.SignType.MD5);
                //发送给微信的xml
                String outputxml = WXPayUtil.mapToXml(data,sign);
                //发送xml获取返回结果
                String resource =this.getClass().getClassLoader().getResource("/").getPath();
                String result = WXPayUtil.requestOnce(Constant.REFUNDURL, nonceStr, outputxml, 6000, 8000, true,resource);


                if (ToolUtil.isNotEmpty(result)) {
                    //将返回的xml转换为map
                    Map<String, String> resultMap = WXPayUtil.xmlToMap(result);

                    //添加退款记录
                    Refund refund = new Refund();
                    refund.setRefundOrderId(onlineOrderId);
                    refund.setRefundMoney(refundMoney);
                    refund.setRefundTime(DateUtil.getTime());
                    refund.setRefundUserId(selectUser.getUserId());

                    if (resultMap.get("return_code").equals("SUCCESS") && resultMap.get("return_msg").equals("OK")) {

                        //退款成功后添加流水
                        CapitalFlow capitalFlow = new CapitalFlow();
                        capitalFlow.setCapitalFlowUserId(selectOnlineOrder.getOnlineOrderUserId());
                        capitalFlow.setCapitalFlowTransactionNumber(selectOnlineOrder.getOnlineOrderDealNumber());
                        capitalFlow.setCapitalFlowTransactionAmount(refundMoney);
                        capitalFlow.setCapitalFlowPaymentType(1);//微信
                        capitalFlow.setCapitalFlowTransactionType(6);//退款
                        capitalFlow.setCapitalFlowTime(DateUtil.getTime());
                        capitalFlow.setCapitalFlowUserMoney(BigDecimalUtils.sub(selectUser.getUserMoney(), refundMoney));
                        capitalFlow.setCapitalFlowState(2);//完成
                        capitalFlow.setCapitalFlowRemarks("退款");
                        this.capitalFlowMapper.insertSelective(capitalFlow);

                        //修改订单退款状态
                        OrderBuy orderBuy = new OrderBuy();
                        if (ToolUtil.isNotEmpty(orderBuyId)) {
                            //单个退款
                            orderBuy.setOrderBuyRefund(1);//已退款
                            orderBuy.setOrderBuyId(orderBuyId);
                            this.orderBuyMapper.updateByPrimaryKeySelective(orderBuy);
                        }else {
                            //一键退款
                            orderBuy.setOrderBuyState(2);//出货失败
                            orderBuy.setOrderBuyParentId(onlineOrderId);
                            List<OrderBuy> orderBuys = this.orderBuyMapper.selectByExampleSelective(orderBuy);
                            for (OrderBuy forOrderBuy: orderBuys) {
                                forOrderBuy.setOrderBuyRefund(1);//已退款
                                this.orderBuyMapper.updateByPrimaryKeySelective(forOrderBuy);
                            }
                        }


                        //修改商户余额
                        selectUser.setUserMoney(BigDecimalUtils.sub(selectUser.getUserMoney(), refundMoney));
                        selectUser.setUserWechatBalance(BigDecimalUtils.sub(selectUser.getUserWechatBalance(), refundMoney));
                        this.userMapper.updateByPrimaryKeySelective(selectUser);

                        //添加提现记录
                        refund.setRefundState(1);
                        this.refundMapper.insertSelective(refund);

                        return Msg.success().add("msg",resultMap);
                    }else {
                        if (resultMap.get("err_code").equals("NOTENOUGH")) {
                            String pushMessage = "微信退款余额不足";
                            PushUtils.getInstance().pushMessage("18654568090", pushMessage);
                            PushUtils.getInstance().pushMessage("15562649697", pushMessage);

                            return Msg.setFailMsg("服务器正在忙于结算，请5-10分钟后再试");
                        }

                        //修改订单退款状态
                        OrderBuy orderBuy = new OrderBuy();
                        if (ToolUtil.isNotEmpty(orderBuyId)) {
                            //单个退款
                            orderBuy.setOrderBuyRefund(2);//退款失败
                            orderBuy.setOrderBuyId(orderBuyId);
                            this.orderBuyMapper.updateByPrimaryKeySelective(orderBuy);
                        }else {
                            //一键退款
                            orderBuy.setOrderBuyState(2);//出货失败
                            orderBuy.setOrderBuyParentId(onlineOrderId);
                            List<OrderBuy> orderBuys = this.orderBuyMapper.selectByExampleSelective(orderBuy);
                            for (OrderBuy forOrderBuy: orderBuys) {
                                forOrderBuy.setOrderBuyRefund(2);//退款失败
                                this.orderBuyMapper.updateByPrimaryKeySelective(forOrderBuy);
                            }
                        }

                        //添加提现记录
                        refund.setRefundState(1);
                        this.refundMapper.insertSelective(refund);

                        return Msg.fail().add("msg",resultMap);
                    }
                }else {
                    return Msg.fail().add("msg", "返回结果为空!!");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }else {
            return Msg.fail().add("msg", "订单信息为空!!");
        }
        return Msg.fail();
    }


    /**
     * 判断是微信提现还是支付宝提现
     * @param userId      商户id
     * @param money       提现金额
     * @param type        提现类型 0.微信提现到零钱 1.支付宝提现到零钱 2.微信提现到银行卡 3.支付宝提现到银行卡
     * @return
     */
    public Msg cashWithDrawalJump(Integer userId, Double money, Integer type, Integer withDrawalId) {
        if (ToolUtil.isNotEmpty(userId) && ToolUtil.isNotEmpty(money) && ToolUtil.isNotEmpty(type)) {
            if (type == 0) {
                //0.微信提现到零钱
                User user = new User();
                user.setUserId(userId);
                User selectUser = this.userMapper.selectByPrimaryKey(user);
                if (ToolUtil.isNotEmpty(selectUser) && ToolUtil.isEmpty(selectUser.getUserCustomerId())) {
                    //如果该用户第一次提现需要获取openid
                    return Msg.fail().add("msg", "商户未授权登陆");
                }else {
                    //该用户已经有了openid，直接提现
                    return this.iwxPayService.wxCashWithdrawal(userId, money, withDrawalId);
                }
            }else if (type == 1) {
                //1.支付宝提现到零钱
                return this.iCustomerService.withdraw(money, userId,type);
            }else if (type == 2 || type == 3) {
                //2.微信提现到银行卡
                //return drawCashService.insertApplyForDrawCash(userId,money,type);
            }
            return Msg.success();
        }else {
            return Msg.fail().add("msg", "传入信息为空");
        }
    }


    /**
     * 授权登陆重定向(商户提现)
     * @param code
     * @param state
     * @return
     */
    public String wxChatCashRedirect(String code, String state){

        logger.error(code);

        //String authorization = request.getHeader(Constants.AUTHORIZATION);
        TokenModel model = this.tokenService.getToken(state);
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //实例化一个Cookie
        Cookie cookie = new Cookie("token", state);
        //生存时间
        cookie.setMaxAge(3600 * 24);
        //设置cookie路径
        cookie.setPath("/");
        //写入肯定是要用response
        response.addCookie(cookie);


        //先从缓存里获取code，然后如果有的话，就不进行操作
        String redisMessage = redisTemplate.boundValueOps("wxcode:" + code).get();
        if (ToolUtil.isNotEmpty(redisMessage)) {
            logger.error("缓存里的openid"+redisMessage);
            //保存微信授权的信息
            Customer customer = new Customer();
            customer.setCustomerOpenId(redisMessage);
            //根据openid查询,判断用户是否存在
            Customer selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);
            if (ToolUtil.isNotEmpty(selectCustomer)) {
                //保存到用户信息
                User user = new User();
                user.setUserId(Integer.parseInt(model.getUserId()));
                user.setUserPreviewCustomerId(selectCustomer.getCustomerId());
                this.userMapper.updateByPrimaryKeySelective(user);
            }
        }else {

            //定义地址
            String requestURL = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", Constant.APPID, Constant.AppSecret,code);
            //获取返回信息
            Map<String, Object> resultMap = WXPayUtil.SendRequest(requestURL, null, "GET");

            if(ToolUtil.isNotEmpty(resultMap)){

                if (ToolUtil.isEmpty(resultMap.get("openid")) || ToolUtil.isEmpty(resultMap.get("access_token"))) {
                    logger.error("提现微信授权登陆错误：错误码（"+resultMap.get("errcode")+")");
                    return "redirect:" + Constant.CASHREDIRECTURL + "&type=0";
                }
                logger.error(resultMap.get("openid"));
                logger.error(resultMap.get("access_token"));
                String openid=(String)resultMap.get("openid");
                String token=(String)resultMap.get("access_token");


                //code只能使用一次，未使用五分钟后过期，所以注意不能使用相同的code获取两次openid
                //保存数据
                //如果检测到使用了相同的code那么就不进行操作了
                redisTemplate.boundValueOps("wxcode:" + code).set((String)resultMap.get("openid"), Constants.MQTT_EXPIRES_HOUR, TimeUnit.SECONDS);


                //获取用户信息请求url
                String userInfoURL = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s", token, openid, Constant.LANG);
                //获取返回信息
                Map<String, Object> userInfoMap = WXPayUtil.SendRequest(userInfoURL, null, "GET");

                if (ToolUtil.isNotEmpty(userInfoMap)) {

                    //保存微信授权的信息
                    Customer customer = new Customer();
                    customer.setCustomerOpenId(openid);

                    //根据openid查询,判断用户是否存在
                    Customer selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);

                    customer.setCustomerName(userInfoMap.get("nickname").toString());
                    customer.setCustomerPhoto(userInfoMap.get("headimgurl").toString());
                    customer.setCustomerSex(userInfoMap.get("sex").toString());
                    customer.setCustomerType(1);//微信用户
                    customer.setCustomerCountry(userInfoMap.get("city").toString());
                    customer.setCustomerCity(userInfoMap.get("city").toString());
                    customer.setCustomerProvince(userInfoMap.get("province").toString());

                    if (ToolUtil.isNotEmpty(selectCustomer)) {
                        //更新客户信息
                        customer.setCustomerId(selectCustomer.getCustomerId());
                        this.customerMapper.updateByPrimaryKeySelective(customer);
                    }else{
                        //添加新的客户信息
                        this.customerMapper.insertSelective(customer);
                    }
                    Customer getIdCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);

                    //保存到用户信息
                    User user = new User();
                    user.setUserId(Integer.parseInt(model.getUserId()));
                    user.setUserPreviewCustomerId(getIdCustomer.getCustomerId());
                    this.userMapper.updateByPrimaryKeySelective(user);
                    logger.error("------授权登陆信息已经保存------");
                }
            }
        }


        return "redirect:" + Constant.CASHREDIRECTURL + "&type=0";
    }


    /**
     * 查询用户是否授权登陆
     * @param userId
     * @return
     */
    public Msg selectUserOpenId(Integer userId) {

        if (ToolUtil.isNotEmpty(userId)) {

            User user = new User();
            user.setUserId(userId);
            User selectUser = this.userMapper.selectByPrimaryKey(user);
            if (ToolUtil.isNotEmpty(selectUser)) {
                if (ToolUtil.isNotEmpty(selectUser.getUserCustomerId())) {
                    return Msg.success().add("msg", "已授权登陆");
                }else {
                    return Msg.fail().add("msg", "未授权登陆");
                }

            }else {
                return Msg.fail().add("msg", "该用户不存在");
            }
        }else {
            return Msg.fail().add("msg", "该用户不存在");
        }
    }



    /**
     * 查询商户提现信息
     * @param userId
     * @return
     */
    public Msg selectUserWechatMessage(Integer userId, Integer type){

        if (ToolUtil.isNotEmpty(userId)) {

            //查询商户信息
            User user = new User();
            user.setUserId(userId);
            User selectUser = this.userMapper.selectByPrimaryKey(user);

            if (ToolUtil.isNotEmpty(selectUser)) {

                //查询微信授权信息
                Customer customer = new Customer();
                if (ToolUtil.isNotEmpty(type)) {//授权页面
                    if (ToolUtil.isNotEmpty(selectUser.getUserPreviewCustomerId())) {
                        customer.setCustomerId(selectUser.getUserPreviewCustomerId());
                    }else {
                        customer.setCustomerId(selectUser.getUserCustomerId());
                    }
                }else {//非授权页面
                    if (ToolUtil.isNotEmpty(selectUser.getUserCustomerId())) {
                        customer.setCustomerId(selectUser.getUserCustomerId());
                    }
                }
                Customer selectCustomer = null;
                if (ToolUtil.isNotEmpty(selectUser.getUserPreviewCustomerId()) || ToolUtil.isNotEmpty(selectUser.getUserCustomerId())) {
                    try {
                        selectCustomer = this.customerMapper.selectByPrimaryKeySelective(customer);
                    }catch (Exception e) {
                        selectCustomer = null;
                    }
                }

                //删除预存的微信授权信息
                //this.userMapper.updateCustomerIdNull(user);

                if (ToolUtil.isNotEmpty(selectCustomer)) {

                    String customerName = selectCustomer.getCustomerName();
                    String customerPhoto = selectCustomer.getCustomerPhoto();

                    return Msg.success().add("CustomerName", customerName).add("CustomerPhoto", customerPhoto).add("userWechatRealName", selectUser.getUserWechatRealName())
                            .add("userAlipayRealName", selectUser.getUserAlipayRealName()).add("userAlipayNumber", selectUser.getUserAlipayNumber());
                }else {
                    return Msg.fail();
                }
            }else {
                return Msg.fail();
            }
        }else {
            return Msg.fail().add("msg", "用户id为空");
        }
     }



    /**
     * 线下订单支付回调
     * @param underlineOrderId
     * @return
     */
    @Override
    public Msg UnderlinePayCallBack(Integer underlineOrderId) {

        //判断订单
        OnlineOrder onlineOrder = new OnlineOrder();
        onlineOrder.setOnlineOrderId(underlineOrderId);
        OnlineOrder selectOnlineOrder = this.onlineOrderMapper.selectByPrimaryKeySelective(onlineOrder);
        if (ToolUtil.isNotEmpty(selectOnlineOrder)) {
            if (selectOnlineOrder.getOnlineOrderState() == 1 || selectOnlineOrder.getOnlineOrderState() == 2) {
                //已经支付过的订单
                return Msg.fail().add("msg", "订单已失效");
            }else {
                //线下订单因为支付时最低支付一元，所以要将商品总价格向上取整到元
                onlineOrder.setOnlineOrderMoney(Math.ceil(selectOnlineOrder.getOnlineOrderMoney()));
                //已支付状态
                onlineOrder.setOnlineOrderState(1);
                //支付类型
                onlineOrder.setOnlineOrderType("3");
                this.onlineOrderMapper.updateByPrimaryKeySelective(onlineOrder);

                //如果在特殊需求的中药表里有该订单的信息，还要修改中药订单的状态
                Medicine medicine = new Medicine();
                medicine.setMedicineOrderId(underlineOrderId);
                Medicine selectMedicine = this.medicineMapper.selectByPrimaryKeySelective(medicine);
                if (ToolUtil.isNotEmpty(selectMedicine)) {
                    medicine.setMedicineStatus(1);
                    this.medicineMapper.updateStatusByOrderId(medicine);
                }
            }
        }

        //发送出货的MQTT消息
        RunnerSendMqtt runnerSendMqtt = new RunnerSendMqtt();
        runnerSendMqtt.setMessage(selectOnlineOrder.getOnlineOrderEquipmentId());
        runnerSendMqtt.setRedisTemplate(redisTemplate);
        runnerSendMqtt.setTheme("Delivery");
        runnerSendMqtt.setThreadName("出货指令");
        runnerSendMqtt.setRedisKey("DeliveryReceive-" + selectOnlineOrder.getOnlineOrderEquipmentId());
        runnerSendMqtt.setOnlineOrderId(underlineOrderId);
        runnerSendMqtt.start();


        //开启了订单推送
        Equipment equipment = new Equipment();
        equipment.setEquipmentId(selectOnlineOrder.getOnlineOrderEquipmentId());
        Equipment selectEquipment = this.equipmentMapper.selectByPrimary(equipment);
        User user = new User();
        user.setUserId(selectEquipment.getEquipmentUserId());
        User selectUser = this.userMapper.selectByPrimaryKey(user);
        if (selectUser != null && selectUser.getUserOrderPush().equals("1")){
            String pushMessage = "订单推送详情:\n设备ID:%s\n商家订单号:%s\n订单金额:%s\n支付方式:%s";
            try {
                PushUtils.getInstance().pushMessage(selectUser.getUserAccount(),String.format(pushMessage, selectEquipment.getEquipmentId(), selectOnlineOrder.getOnlineOrderMerchantNumber(),
                        selectOnlineOrder.getOnlineOrderMoney(), "现金支付"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return Msg.success();
    }

}
